package com.phuc.game.tankshooter.engine;

import java.io.IOException;
import java.util.ArrayList;

import org.anddev.andengine.audio.music.Music;
import org.anddev.andengine.audio.music.MusicFactory;
import org.anddev.andengine.audio.sound.Sound;
import org.anddev.andengine.audio.sound.SoundFactory;
import org.anddev.andengine.engine.Engine;
import org.anddev.andengine.entity.scene.Scene;
import org.anddev.andengine.entity.scene.background.SpriteBackground;
import org.anddev.andengine.util.MathUtils;

import android.content.Context;
import android.util.Log;

import com.phuc.game.tankshooter.MainActivity;
import com.phuc.game.tankshooter.sprite.Background1Sprite;
import com.phuc.game.tankshooter.sprite.BulletCountTotalSprite;
import com.phuc.game.tankshooter.sprite.EnemyObjectSprite;
import com.phuc.game.tankshooter.sprite.ExplodeSprite;
import com.phuc.game.tankshooter.sprite.FuelTruckDeadSprite;
import com.phuc.game.tankshooter.sprite.GunSprite;
import com.phuc.game.tankshooter.sprite.ItemSprite;
import com.phuc.game.tankshooter.sprite.RocketSprite;
import com.phuc.game.tankshooter.sprite.SmokeSprite;
import com.phuc.game.tankshooter.sprite.TankDeadSprite;
import com.phuc.game.tankshooter.sprite.WallSprite;

public class GamePlay {
	private WelcomeScene welcomeScene;

	private boolean gameIsRunning;
	private ThreadCreateEnemy threadCreateEnemy;
	GunSprite gun;
	WallSprite wall;
	BulletCountTotalSprite bulletCount;
	
	private int point;
	private int rocketNum;
	private int rocketNumTotal;
	private int rocketBigNum;
	private int life;
	int time;
	int timePhase;
	private int phaseAttack;
	
	private ArrayList<Integer> listPhaseEnemyAdd = new ArrayList<Integer>();
	private ArrayList<Integer> listPhaseEnemyGroup = new ArrayList<Integer>();
	
	public static int tankAKill;
	public static int tankT34Kill;
	public static int tankMoleKill;
	public static int tankTigerKill;

	public GamePlay() {
		// Init data
		tankAKill = 0;
		tankT34Kill = 0;
		tankMoleKill = 0;
		tankTigerKill = 0;
		point = 0;
		rocketNum = 15;
		rocketNumTotal = 15;
		life = 4;
		time = 0;
		timePhase = 0;
		phaseAttack = 1;
		
		resume();
		EnemyObjectSprite.tankEnemy.clear();
		ItemSprite.listItemSprites.clear();
		
		// Add first phase
		for (int id : AIFactory.PhaseEnemyAdd.PHASE_1) {
			listPhaseEnemyAdd.add(id);
		}

		for (int id : AIFactory.PhaseEnemyGroup.PHASE_1) {
			listPhaseEnemyGroup.add(id);
		}
		
		Log.d("phucphuc", "phucphuc GamePlay start");
	}
	
	public void pause() {
		gameIsRunning = false;
		try {
			threadCreateEnemy.join();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		if (music != null) {
			music.pause();
		}
	}
	
	public void resume() {
		gameIsRunning = true;
		threadCreateEnemy = new ThreadCreateEnemy();
		threadCreateEnemy.start();
		
		try {
			if (music != null) {
				music.resume();
			}
		} catch (IllegalStateException ex) { }
	}

	public Scene getWelcomeScene() {
		Background1Sprite faceSpr = new Background1Sprite(
				textureBackground1.getFaceTiledTextureRegion(), welcomeScene);
		SpriteBackground background = new SpriteBackground(faceSpr);
		welcomeScene = new WelcomeScene(background);

		// Init gun and wall
		wall = new WallSprite(textureWall.getFaceTiledTextureRegion(),
				welcomeScene);
		welcomeScene.attachChild(wall);
		gun = new GunSprite(textureGun.getFaceTiledTextureRegion(),
				welcomeScene);
		welcomeScene.attachChild(gun);
		
		bulletCount = new BulletCountTotalSprite();
		welcomeScene.attachChild(bulletCount);

		return welcomeScene;
	}

	public void createExplode(float pX, float pY) {
		ExplodeSprite faceSpr = new ExplodeSprite(pX - ExplodeSprite.WIDTH / 2,
				pY - ExplodeSprite.HEIGHT / 2, ExplodeSprite.WIDTH,
				ExplodeSprite.HEIGHT,
				textureExplode.getFaceTiledTextureRegion(), welcomeScene);
		welcomeScene.attachChild(faceSpr);
		playRocketEx();
	}
	
	public void createExplodeWithSize(float pX, float pY, int size) {
		int width = ExplodeSprite.WIDTH;
		if (size == ExplodeSprite.EXPLODE_SIZE_SMALL) {
			width /= 2;
		} else if (size == ExplodeSprite.EXPLODE_SIZE_LARGE) {
			width = 3 * width / 2;
		}

		ExplodeSprite faceSpr = new ExplodeSprite(pX - width / 2,
				pY - width / 2, width, width,
				textureExplode.getFaceTiledTextureRegion(), welcomeScene);
		welcomeScene.attachChild(faceSpr);
		playRocketEx();
	}

	public void createRocket(float pX, float pY) {
		RocketSprite faceSpr = new RocketSprite(pX - RocketSprite.WIDTH / 2,
				pY, RocketSprite.WIDTH, RocketSprite.HEIGHT,
				textureRocket.getFaceTiledTextureRegion(), welcomeScene);
		welcomeScene.attachChild(faceSpr);
		decreaseRocketNum();
		if (rocketNum < 0) {
			restoreRocketNum();
		}
		playGunSound();
	}

	public void createTankDead(int index, float pX, float pY, float pTileWidth,
			float pTileHeight, float rotation) {
		TankDeadSprite faceSpr = new TankDeadSprite(pX, pY, pTileWidth,
				pTileHeight, textureTankDead.getFaceTiledTextureRegion(),
				rotation, welcomeScene);
		welcomeScene.attachChild(faceSpr, index);
	}
	
	public void createTruckDead(int index, float pX, float pY, float pTileWidth,
			float pTileHeight, float rotation) {
		FuelTruckDeadSprite faceSpr = new FuelTruckDeadSprite(pX, pY, pTileWidth,
				pTileHeight, textureTankDead.getFaceTiledTextureRegion(),
				rotation, welcomeScene);
		welcomeScene.attachChild(faceSpr, index);
	}

	public void createSmoke(float pX, float pY, int type) {
		int size = 70;
		if (type == 0) {
			size = 70;
		} else if (type == 1) {
			size = 25;
		}

		SmokeSprite faceSpr = new SmokeSprite(pX, pY, size, size,
				textureSmoke.getFaceTiledTextureRegion(), welcomeScene);
		welcomeScene.attachChild(faceSpr);
	}

	/**
	 * Thread run to create enemies.
	 */
	class ThreadCreateEnemy extends Thread {

		@Override
		public void run() {
			while (gameIsRunning) {
				try {
					sleep(1000);
					time++;
					timePhase++;
					if (timePhase > AIFactory.TIME_PER_PHASE) {
						timePhase = 0;
						phaseAttack++;
						
						// Add phase id
						int currentPhaseTmp = phaseAttack;
						if (currentPhaseTmp >= AIFactory.PhaseEnemyAdd.PHASES.length) {
							currentPhaseTmp = AIFactory.PhaseEnemyAdd.PHASES.length - 1;
						}
						for (int id : AIFactory.PhaseEnemyAdd.PHASES[currentPhaseTmp]) {
							listPhaseEnemyAdd.add(id);
						}
						for (int id : AIFactory.PhaseEnemyGroup.PHASES[currentPhaseTmp]) {
							listPhaseEnemyGroup.add(id);
						}
					}
				} catch (InterruptedException e) { }

				if (phaseAttack <= 14) {
					// Call army each 4 second
					// when time > 40, not call
					if (timePhase % 4 == 0 && timePhase < 54) {
						int rand = MathUtils.random(0, listPhaseEnemyAdd.size() - 1);
						EnemyFactory.createEnemy(listPhaseEnemyAdd.get(rand), null);
						if (timePhase % 16 == 0) {
							rand = MathUtils.random(0, listPhaseEnemyAdd.size() - 1);
							EnemyFactory.createEnemy(listPhaseEnemyAdd.get(rand), null);
						}
					}
					
					// Call group each 10 second, call when time >= 30
					if (timePhase % 10 == 0 && timePhase > 29 && timePhase < 60) {
						int row = MathUtils.random(2, 5);
						int column = MathUtils.random(2, 5);
						int rand = MathUtils.random(0, listPhaseEnemyGroup.size() - 1);
						int tankId = listPhaseEnemyGroup.get(rand);
						EnemyFactory.createGroupOneType(tankId, row, column,
								EnemyFactory.getRangeOfTankGroup(tankId), MathUtils.random(2, 3));
					}
					
					// Call boss
					if (timePhase % 60 == 0) {
						int currentPhaseTmp = phaseAttack;
						if (currentPhaseTmp >= AIFactory.PhaseBoss.PHASES.length) {
							currentPhaseTmp = AIFactory.PhaseBoss.PHASES.length - 1;
						}
						EnemyFactory.createEnemy(AIFactory.PhaseBoss.PHASES[currentPhaseTmp], null);
					}
					
					// Create Item Rocket
					if (timePhase % 40 == 0) {
						ItemSprite sprite = new ItemSprite(ItemSprite.TYPE_ROCKET,
								GamePlay.textureItemRocket.getFaceTiledTextureRegion());
						welcomeScene.attachChild(sprite);
					}
					
					// Create Item Score
					if (timePhase % 17 == 0) {
						ItemSprite sprite = new ItemSprite(ItemSprite.TYPE_POINT,
								GamePlay.textureItem10Point.getFaceTiledTextureRegion());
						welcomeScene.attachChild(sprite);
					}
					
					if (time % 90 == 0) {
						ItemSprite sprite = new ItemSprite(ItemSprite.TYPE_DEAD,
								GamePlay.textureItemDead.getFaceTiledTextureRegion());
						welcomeScene.attachChild(sprite);
					}
				} else {
					// After 14 turn
					// Call army each 2 second
					// when time > 40, not call
					if (timePhase % 2 == 0 && timePhase < 54) {
						int rand = MathUtils.random(0, listPhaseEnemyAdd.size() - 1);
						EnemyFactory.createEnemy(listPhaseEnemyAdd.get(rand), null);
						if (timePhase % 8 == 0) {
							rand = MathUtils.random(0, listPhaseEnemyAdd.size() - 1);
							EnemyFactory.createEnemy(listPhaseEnemyAdd.get(rand), null);
						}
					}

					// Call group each 10 second, call when time >= 30
					if (timePhase % 10 == 0 && timePhase < 60) {
						int row = MathUtils.random(2, 5);
						int column = MathUtils.random(2, 5);
						int rand = MathUtils.random(0, listPhaseEnemyGroup.size() - 1);
						int tankId = listPhaseEnemyGroup.get(rand);
						EnemyFactory.createGroupOneType(tankId, row, column,
								EnemyFactory.getRangeOfTankGroup(tankId), MathUtils.random(2, 3));
					}

					// Call boss
					if (timePhase % 20 == 0) {
						int currentPhaseTmp = phaseAttack;
						if (currentPhaseTmp >= AIFactory.PhaseBoss.PHASES.length) {
							currentPhaseTmp = AIFactory.PhaseBoss.PHASES.length - 1;
						}
						EnemyFactory.createEnemy(AIFactory.PhaseBoss.PHASES[currentPhaseTmp], null);
					}
					
					if (time % 20 == 0) {
						ItemSprite sprite = new ItemSprite(ItemSprite.TYPE_DEAD,
								GamePlay.textureItemDead.getFaceTiledTextureRegion());
						welcomeScene.attachChild(sprite);
					}
				}
				
			}
		}
	}

	public GunSprite getGun() {
		return gun;
	}

	/// Textures
	public static TextureCommon textureExplode;
	public static TextureCommon textureRocket;
	public static TextureCommon textureSmoke;
	public static TextureCommon textureBackground1;
	public static TextureCommon textureGun;
	public static TextureCommon textureWall;
	public static TextureCommon textureEnemyTankTigerRed;
	public static TextureCommon textureEnemyTankTigerGreen;
	public static TextureCommon textureEnemyTankTigerGold;
	public static TextureCommon textureEnemyTankARed;
	public static TextureCommon textureEnemyTankAGreen;
	public static TextureCommon textureEnemyTankAGold;
	public static TextureCommon textureEnemyTankMoleOrange;
	public static TextureCommon textureEnemyTankMolePuple;
	public static TextureCommon textureEnemyTankT34Red;
	public static TextureCommon textureEnemyTankT34Green;
	public static TextureCommon textureEnemyTankT34Gold;
	public static TextureCommon textureEnemyTruck;
	public static TextureCommon textureEnemyFuelTruck;
	public static TextureCommon textureTankDead;
	
	public static TextureCommon textureItemHeart;
	public static TextureCommon textureItemRocket;
	public static TextureCommon textureItemRocketBig;
	public static TextureCommon textureItem10Point;
	public static TextureCommon textureItemDead;
	
	public static TextureCommon textureBulletNumTotal;
	public static TextureCommon textureBulletNum;

	public static void initTextures(Engine mEngine, Context context) {

		GamePlay.textureExplode = TextureFactory.createExplode(context);
		mEngine.getTextureManager().loadTexture(
				GamePlay.textureExplode.getFaceTexture());

		GamePlay.textureRocket = TextureFactory.createRocket(context);
		mEngine.getTextureManager().loadTexture(
				GamePlay.textureRocket.getFaceTexture());

		GamePlay.textureSmoke = TextureFactory.createSmoke(context);
		mEngine.getTextureManager().loadTexture(
				GamePlay.textureSmoke.getFaceTexture());

		GamePlay.textureBackground1 = TextureFactory
				.createBackground1(context);
		mEngine.getTextureManager().loadTexture(
				GamePlay.textureBackground1.getFaceTexture());

		GamePlay.textureEnemyTankTigerRed = TextureFactory.createTankTigerRed(context);
		mEngine.getTextureManager().loadTexture(
				GamePlay.textureEnemyTankTigerRed.getFaceTexture());
		GamePlay.textureEnemyTankTigerGreen = TextureFactory.createTankTigerGreen(context);
		mEngine.getTextureManager().loadTexture(
				GamePlay.textureEnemyTankTigerGreen.getFaceTexture());
		GamePlay.textureEnemyTankTigerGold = TextureFactory.createTankTigerGold(context);
		mEngine.getTextureManager().loadTexture(
				GamePlay.textureEnemyTankTigerGold.getFaceTexture());

		GamePlay.textureTankDead = TextureFactory.createTankDead(context);
		mEngine.getTextureManager().loadTexture(
				GamePlay.textureTankDead.getFaceTexture());

		GamePlay.textureGun = TextureFactory.createGun(context);
		mEngine.getTextureManager().loadTexture(
				GamePlay.textureGun.getFaceTexture());

		GamePlay.textureWall = TextureFactory.createWall(context);
		mEngine.getTextureManager().loadTexture(
				GamePlay.textureWall.getFaceTexture());
		
		GamePlay.textureBulletNumTotal = TextureFactory.createBulletTotal(context);
		mEngine.getTextureManager().loadTexture(
				GamePlay.textureBulletNumTotal.getFaceTexture());
		
		GamePlay.textureBulletNum = TextureFactory.createBulletCount(context);
		mEngine.getTextureManager().loadTexture(
				GamePlay.textureBulletNum.getFaceTexture());
		
		GamePlay.textureEnemyTankARed = TextureFactory.createTankARed(context);
		mEngine.getTextureManager().loadTexture(
				GamePlay.textureEnemyTankARed.getFaceTexture());
		GamePlay.textureEnemyTankAGreen = TextureFactory.createTankAGreen(context);
		mEngine.getTextureManager().loadTexture(
				GamePlay.textureEnemyTankAGreen.getFaceTexture());
		GamePlay.textureEnemyTankAGold = TextureFactory.createTankAGold(context);
		mEngine.getTextureManager().loadTexture(
				GamePlay.textureEnemyTankAGold.getFaceTexture());

		GamePlay.textureEnemyTankMoleOrange = TextureFactory.createTankMoleOrange(context);
		mEngine.getTextureManager().loadTexture(
				GamePlay.textureEnemyTankMoleOrange.getFaceTexture());
		GamePlay.textureEnemyTankMolePuple = TextureFactory.createTankMolePuple(context);
		mEngine.getTextureManager().loadTexture(
				GamePlay.textureEnemyTankMolePuple.getFaceTexture());

		GamePlay.textureEnemyTankT34Red = TextureFactory.createTankT34Red(context);
		mEngine.getTextureManager().loadTexture(
				GamePlay.textureEnemyTankT34Red.getFaceTexture());
		GamePlay.textureEnemyTankT34Green = TextureFactory.createTankT34Green(context);
		mEngine.getTextureManager().loadTexture(
				GamePlay.textureEnemyTankT34Green.getFaceTexture());
		GamePlay.textureEnemyTankT34Gold= TextureFactory.createTankT34Gold(context);
		mEngine.getTextureManager().loadTexture(
				GamePlay.textureEnemyTankT34Gold.getFaceTexture());

		GamePlay.textureEnemyTruck = TextureFactory.createTruck(context);
		mEngine.getTextureManager().loadTexture(
				GamePlay.textureEnemyTruck.getFaceTexture());

		GamePlay.textureEnemyFuelTruck = TextureFactory.createFuelTruck(context);
		mEngine.getTextureManager().loadTexture(
				GamePlay.textureEnemyFuelTruck.getFaceTexture());

		GamePlay.textureItemHeart = TextureFactory.createItemHeart(context);
		mEngine.getTextureManager().loadTexture(
				GamePlay.textureItemHeart.getFaceTexture());
		GamePlay.textureItemRocket = TextureFactory.createItemRocket(context);
		mEngine.getTextureManager().loadTexture(
				GamePlay.textureItemRocket.getFaceTexture());
		GamePlay.textureItemRocketBig = TextureFactory.createItemRocketBig(context);
		mEngine.getTextureManager().loadTexture(
				GamePlay.textureItemRocketBig.getFaceTexture());
		GamePlay.textureItem10Point = TextureFactory.createItem10Point(context);
		mEngine.getTextureManager().loadTexture(
				GamePlay.textureItem10Point.getFaceTexture());
		GamePlay.textureItemDead = TextureFactory.createItemDead(context);
		mEngine.getTextureManager().loadTexture(
				GamePlay.textureItemDead.getFaceTexture());
	}

	// Sound
	private static Music music;
	private static Sound mSound = null;
	private static Sound mExplode = null;
	private static Sound mRocketEx = null;
	
	public static void initMusic(Engine mEngine, Context context) {
		SoundFactory.setAssetBasePath("sound/");
		try {
			music = MusicFactory.createMusicFromAsset(mEngine.getMusicManager(), context, "sound/swords.mp3");
			music.setLooping(true);
			music.setVolume(0.7f);
			music.play();
		} catch (IllegalStateException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
        
        try {
    		mSound = SoundFactory.createSoundFromAsset(mEngine.getSoundManager(), context, "bullet_wizzing.wav");
            mSound.setVolume(0.4f);
            
        	mExplode = SoundFactory.createSoundFromAsset(mEngine.getSoundManager(), context, "bomb2.wav");
         	mExplode.setVolume(0.1f);
            
        	mRocketEx = SoundFactory.createSoundFromAsset(mEngine.getSoundManager(), context, "bomb2.wav");
        	mRocketEx.setVolume(0.2f);
           
        } catch (final IOException e) {
        	Log.d("phucphuc", "phucphuc aaaaaaa");
        }
	}
	
	public static void playGunSound() {
		mSound.stop();
        mSound.play();
	}
	
	public static void playExplode() {
		mExplode.stop();
		mExplode.play();
	}
	
	public static void playRocketEx() {
		mRocketEx.stop();
		mRocketEx.play();
	}
	
	public void addPoint(int point) {
		this.point += point;
		MainActivity.getInstant().setPointToText();
	}
	
	public int getPoint() {
		return point;
	}
	
	public void addRocketNumTotal(int num) {
		this.rocketNumTotal += num;
		MainActivity.getInstant().setBulletNumToView();
	}
	
	public int getRocketNumTotal() {
		return rocketNumTotal;
	}
	
	public void decreaseRocketNum() {
		this.rocketNum--;
		MainActivity.getInstant().setBulletNumToView();
	}
	
	public void restoreRocketNum() {
		rocketNum = rocketNumTotal;
		MainActivity.getInstant().setBulletNumToView();
	}
	
	public int getRocketNum() {
		return rocketNum;
	}
	
	boolean endgame = false;
	
	public void decreaseLife(int num) {
		life -= num;
		if (num > 0) {
			MainActivity.getInstant().setLifeToView();
		}
		if (life <= 0 && !endgame) {
			endgame = true;
			// If life < 0, end game
			new Thread(new Runnable() {
				@Override
				public void run() {
					try {
						for (int i = 0; i < 9; i++) {
							int pX = i * (MainActivity.SCENE_WIDTH - 100) / 6;
							createExplodeWithSize(pX, MainActivity.SCENE_END_LOCATION + 50, 0);
							Thread.sleep(200);
						}
						for (int i = 0; i < 9; i++) {
							int pX = i * (MainActivity.SCENE_WIDTH - 50) / 6;
							createExplodeWithSize(pX, MainActivity.SCENE_END_LOCATION + 100, 0);
							Thread.sleep(200);
						}
						MainActivity.getInstant().runFromUpdateThread(new Runnable() {
							@Override
							public void run() {
								gun.detachSelf();
								wall.detachSelf();
							}
						});
						MainActivity.getInstant().requestEndGame();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}).start();
		}
	}
	
	public int getLife() {
		return life;
	}
	
	public int getRocketBigNum() {
		return rocketBigNum;
	}
	
	public void addRocketBigNum(int num) {
		this.rocketBigNum += num;
	}
	
	public Scene getScene() {
		return this.welcomeScene;
	}
	
	public void endGame() {
		gameIsRunning = false;
		welcomeScene.clearEntityModifiers();
		welcomeScene.clearTouchAreas();
		welcomeScene.clearUpdateHandlers();
		try {
			threadCreateEnemy.join();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		if (music != null) {
			music.stop();
		}
		if (mSound != null) {
			mSound.stop();
		}
		if (mExplode != null) {
			mExplode.stop();
		}
		if (mRocketEx != null) {
			mExplode.stop();
		}
//		mSound.release();
//		mExplode.release();
//		mRocketEx.release();
		listPhaseEnemyAdd.clear();
		listPhaseEnemyAdd.clear();
	}
	
	public void reloadBulletNum() {
		bulletCount.reload();
	}
}
